package com.wynn.service.impl;

import com.wynn.Exception.MyException;
import com.wynn.configuration.PlanTask;
import com.wynn.dao.PlanDao;
import com.wynn.dao.ProductDao;
import com.wynn.dao.ProductLineDao;
import com.wynn.pojo.*;
import com.wynn.service.PlanService;
import com.wynn.utils.DateUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.util.*;

@Slf4j
@Transactional
@RestController
@RequestMapping("plan")
public class PlanServiceImpl implements PlanService {

    @Autowired
    private PlanDao planDao;
    @Autowired
    private ProductDao productDao;
    @Autowired
    private ProductLineDao productLineDao;
    @Autowired
    private PlanTask planTask;


    @Override
    @GetMapping("chartData1")
    public Result getChartData1() {
        Result result = new Result();
        try{

            HashMap<String, Object> chartData = new HashMap<>();

            //查询所有的产品
            List<Product> productList = productDao.findAllProduct();
            //取出产品的名字
            List<String> productNames = new ArrayList<>();
            for (Product product : productList) {
                productNames.add(product.getProductName());
            }
            //横坐标
            chartData.put("labels",productNames);

            //查询所有的产线
            List<ProductLine> lineList = productLineDao.findAllProductLine();
            //存放数据表datasets数据集

            List<HashMap<String, Object>> datasets = new ArrayList<>();
            for (ProductLine productLine : lineList) {
                HashMap<String, Object> dataset = new HashMap<>();

                //用来存放该产线每种产品数量，位置与productNames的位置相对应
                int[] productNum = new int[productList.size()];
                //查询本周某条产线的生产计划
                List<Plan> planList = planDao.findPlanByLineWeekly(productLine.getId());


                for (Plan plan : planList) {
                    //累加每条产线的生产计划
                    //便利所所有产品，找到该订单涉及产品并计数
                    for (int i = 0; i < productList.size(); i++) {
                        if (plan.getProduct().getId()
                                ==productList.get(i).getId()){
                            productNum[i]+=plan.getNumber();
                            break;
                        }
                    }

                }
                dataset.put("label",productLine.getLineName());
                dataset.put("data",productNum);
                datasets.add(dataset);
            }

            //表一数据
            chartData.put("datasets",datasets);
            result.setCode("200");
            result.setData(chartData);
            log.info("周生产统计表查询");
        }catch (Exception e){
            result.setCode("503");
            result.setMessage("周生产统计表查询错误");
            log.warn("周生产统计表查询错误");
        }
        return result;
    }

    @Override
    @GetMapping("selectAll")
    public List<PlanSummary> selectAll(){
        //查询所有产品
        List<Product> allProduct = productDao.findAllProduct();
        //按时间和产线分组查询
        List<PlanSummary> plans  = planDao.findSummary();
        findProuductNum(allProduct, plans);
        return plans;
    }

    @Override
    @PostMapping("addPlan")
    //将一条生产任务按照每个产品拆成若干记录
    public void addPlan(@RequestBody PlanSummary planSummary)throws MyException {

        //1、首先查询所有的产品
        List<Product> allProduct = productDao.findAllProduct();
        //2、获取计划时间和产线
        Date produceDate = DateUtils.dateAdd1(planSummary.getProduceDate());
        ProductLine productLine = planSummary.getProductLine();
        for (Product product : allProduct) {

            //3、逐条插入生产计划
            Integer num = planSummary.getProductsNum().get(product.getProductModel());
            //若添加时没有赋值，则不添加
            if(num!=null){
                Integer flag = planDao.findProductNum(produceDate,productLine,product);
                if(flag!=null){
                    throw new MyException("当日产品"+product.getProductName()+"生产任务已存在不可重复添加");
                }
                planDao.addPlan(produceDate,productLine.getId(),product.getId(),num);
            }

        }
    }

    @Override
    @PostMapping("editPlan")
    public void editPlan(@RequestBody PlanSummary planSummary) {

        Date produceDate = planSummary.getProduceDate();
        ProductLine productLine = planSummary.getProductLine();
        Map<String,Integer> mapNum = planSummary.getProductsNum();
        for (Map.Entry<String, Integer> map : mapNum.entrySet()) {
            Product product = new Product();
            product.setProductModel(map.getKey());
            product = productDao.selectByModel(product);
            //判断是否存在改生产任务
            //若存在则修改数量
            //若不存在添加生产任务
            Integer number = planDao.findProductNum(produceDate,productLine,product);
            if(number==null && map.getValue()!=0){
                planDao.addPlan(produceDate,productLine.getId(),product.getId(),map.getValue());
            }else if(number!=null){
                planDao.editPlan(produceDate,productLine,product.getId(),map.getValue());
            }

        }

    }

    @Override
    @PostMapping("deletePlan")
    public void deletePlan(@RequestBody PlanSummary planSummary) {

        planDao.deletePlan(planSummary.getProduceDate(),planSummary.getProductLine());

    }

    @Override
    @PostMapping("search")
    public List<PlanSummary> search(@RequestBody ProductLine productLine, Date produceDate) {

        //查询所有产品
        List<Product> allProduct = productDao.findAllProduct();
        //按时间和产线分组查询
        List<PlanSummary> plans  = planDao.searchPlan(productLine,produceDate);
        findProuductNum(allProduct, plans);
        return plans;
    }

    @Override
    @PostMapping("searchOnePlan")
    public List<PlanSummary> searchOnePlan(@RequestBody ProductLine productLine, Date produceDate) {

        //查询所有产品
        List<Product> allProduct = productDao.findAllProduct();
        //按时间和产线分组查询
        PlanSummary planSummary  = planDao.searchOnePlan(productLine,DateUtils.dateAdd1(produceDate));
        ArrayList<PlanSummary> plans = new ArrayList<>();
        if (planSummary == null){
            return plans;
        }
        plans.add(planSummary);
        findProuductNum(allProduct, plans);
        return plans;
    }

    //用于搜索和加载产品列表时 对数据库中表的整合
    private void findProuductNum(List<Product> allProduct, List<PlanSummary> plans) {
        for (PlanSummary plan : plans) {
            Map<String, Integer> productNum = new HashMap<>();
            for (Product product : allProduct) {
                Integer tpaln = planDao.findProductNum(plan.getProduceDate(),plan.getProductLine(),product);
                if(tpaln==null){
                    tpaln=0;
                }
                productNum.put(product.getProductModel(),tpaln);
            }
            plan.setProductsNum(productNum);
        }
    }

    @Override
    @PostMapping("importPlan")
    public void importPlan(@RequestBody ArrayList<ArrayList<String>> table, Date produceDate) {

        //将当月的计划全部删除
        planDao.deletePlanByMonth(produceDate);

        //用于存放产品型号和id
        Map<String,Integer> productMap = new HashMap<>();
        List<Product> allProduct = productDao.findAllProduct();
        for (Product product : allProduct) {
            productMap.put(product.getProductModel(),product.getId());
        }
        //用于存放产线名称和Id
        Map<String,Integer> productLineMap = new HashMap<>();
        List<ProductLine> allProductLine = productLineDao.findAllProductLine();
        for (ProductLine productLine : allProductLine) {
            productLineMap.put(productLine.getLineName(),productLine.getId());
        }
        
        int productSize = allProduct.size();
        int planSize = table.size();

        Date tProduceDate;
        int tProductLine;
        int tProduct;
        int tNumber;
        //表格从第三列开始为产品
        for (int j = 3; j < 3+productSize ; j++) {
            //该列的产品型号对应的id
            tProduct = productMap.get(table.get(0).get(j));
            for ( int i = 1; i< planSize ; i++){
                 //该计划生产数量
                tNumber = Integer.parseInt(table.get(i).get(j));
                if (tNumber!=0){
                    //该计划生产时间
                    tProduceDate = DateUtils.stringToDate(table.get(i).get(1));
                    System.out.println(table.get(i).get(1));
                    //该计划所在产线
                    tProductLine = productLineMap.get(table.get(i).get(2));
                    planDao.addPlan(tProduceDate,tProductLine,tProduct,tNumber);
                }
            }
        }

    }

    @Override
    @PostMapping("schedule")
    public Schedule schedule(Date produceDate,@RequestBody ProductLine productLine) {
        Schedule schedule = planDao.findSchedule(DateUtils.dateAdd1(produceDate),productLine);
        return schedule;
    }

    //计算生产任务
    @Override
    @PostMapping("calculation")
    public void calculation(@RequestBody PlanSummary planSummary){
        int productLine = planSummary.getProductLine().getId();
        Date produceDate = planSummary.getProduceDate();
        //讲该生产任务设置为计算状态
        planDao.addCalcuStatue(productLine,produceDate,1);
        //计算该任务
        planTask.plan(planSummary);

    }

    //查询改生产任务的状态
    @Override
    @PostMapping("calcuStatue")
    public CalcuStatue calcuStatue(@RequestBody SearchPlan searchPlan){
        //查询该计划是否处于计算状态
        return planDao.calcuStatue(DateUtils.dateAdd1(searchPlan.getProduceDate()),searchPlan.getProductLine().getId());
    }

}
